import pygame
import random
import sys

# 确保中文正常显示
pygame.init()

# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
TILE_SIZE = 32
WORLD_WIDTH = 200
WORLD_HEIGHT = 60

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BROWN = (139, 69, 19)
GRAY = (128, 128, 128)
DIRT = (101, 67, 33)
GRASS = (34, 139, 34)
STONE = (169, 169, 169)

# 物品类型
DIRT_BLOCK = 1
GRASS_BLOCK = 2
STONE_BLOCK = 3
AIR = 0

# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Python版泰拉瑞亚")

# 创建时钟对象控制帧率
clock = pygame.time.Clock()

class Player:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = TILE_SIZE // 2
        self.height = TILE_SIZE
        self.speed = 5
        self.jump_power = -15
        self.gravity = 0.8
        self.velocity_y = 0
        self.on_ground = False
        self.health = 100
        self.inventory = {DIRT_BLOCK: 0, GRASS_BLOCK: 0, STONE_BLOCK: 0}
        self.selected_item = GRASS_BLOCK
        
    def draw(self, surface, camera_x, camera_y):
        # 绘制玩家
        player_rect = pygame.Rect(self.x - camera_x, self.y - camera_y, self.width, self.height)
        pygame.draw.rect(surface, BLUE, player_rect)
        
        # 绘制健康条
        health_bar_width = self.width
        health_bar_height = 5
        health_bar_x = self.x - camera_x
        health_bar_y = self.y - camera_y - 10
        
        # 背景
        pygame.draw.rect(surface, RED, (health_bar_x, health_bar_y, health_bar_width, health_bar_height))
        # 当前血量
        current_health_width = int(health_bar_width * (self.health / 100))
        pygame.draw.rect(surface, GREEN, (health_bar_x, health_bar_y, current_health_width, health_bar_height))
    
    def move(self, world):
        # 重置移动变量
        dx = 0
        dy = 0
        
        # 处理键盘输入
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            dx = -self.speed
        if keys[pygame.K_RIGHT]:
            dx = self.speed
        if keys[pygame.K_SPACE] and self.on_ground:
            self.velocity_y = self.jump_power
            self.on_ground = False
            
        # 切换选中的物品
        if keys[pygame.K_1]:
            self.selected_item = DIRT_BLOCK
        if keys[pygame.K_2]:
            self.selected_item = GRASS_BLOCK
        if keys[pygame.K_3]:
            self.selected_item = STONE_BLOCK
        
        # 应用重力
        self.velocity_y += self.gravity
        dy += self.velocity_y
        
        # 限制最大下落速度
        if self.velocity_y > 10:
            self.velocity_y = 10
        
        # 碰撞检测
        self.on_ground = False
        
        # X轴碰撞
        for i in range(0, self.width, TILE_SIZE):
            for j in range(0, self.height, TILE_SIZE):
                # 计算下一个位置的格子坐标，确保转换为整数
                next_x = int((self.x + dx + i) // TILE_SIZE)
                next_y = int((self.y + j) // TILE_SIZE)
                
                # 检查是否在世界范围内
                if 0 <= next_x < WORLD_WIDTH and 0 <= next_y < WORLD_HEIGHT:
                    # 如果下一个位置不是空气，则不能移动
                    if world[next_y][next_x] != AIR:
                        if dx > 0:  # 向右移动
                            self.x = next_x * TILE_SIZE - self.width - 1
                        if dx < 0:  # 向左移动
                            self.x = next_x * TILE_SIZE + TILE_SIZE
                        dx = 0
        
        # Y轴碰撞
        for i in range(0, self.width, TILE_SIZE):
            for j in range(0, self.height, TILE_SIZE):
                # 计算下一个位置的格子坐标，确保转换为整数
                next_x = int((self.x + i) // TILE_SIZE)
                next_y = int((self.y + dy + j) // TILE_SIZE)
                
                # 检查是否在世界范围内
                if 0 <= next_x < WORLD_WIDTH and 0 <= next_y < WORLD_HEIGHT:
                    # 如果下一个位置不是空气，则不能移动
                    if world[next_y][next_x] != AIR:
                        if dy > 0:  # 下落
                            self.y = next_y * TILE_SIZE - self.height
                            self.velocity_y = 0
                            self.on_ground = True
                        if dy < 0:  # 上升
                            self.y = next_y * TILE_SIZE + TILE_SIZE
                            self.velocity_y = 0
                        dy = 0
        
        # 更新位置
        self.x += dx
        self.y += dy
        
        # 确保玩家不会走出世界边界
        if self.x < 0:
            self.x = 0
        if self.x + self.width > WORLD_WIDTH * TILE_SIZE:
            self.x = WORLD_WIDTH * TILE_SIZE - self.width
            
    def mine_block(self, world, mouse_pos, camera_x, camera_y):
        # 计算鼠标点击的世界坐标，确保转换为整数
        world_x = int((mouse_pos[0] + camera_x) // TILE_SIZE)
        world_y = int((mouse_pos[1] + camera_y) // TILE_SIZE)
        
        # 检查是否在世界范围内
        if 0 <= world_x < WORLD_WIDTH and 0 <= world_y < WORLD_HEIGHT:
            # 获取被挖掘的方块类型
            block_type = world[world_y][world_x]
            if block_type != AIR:
                # 增加物品到 inventory
                self.inventory[block_type] += 1
                # 移除方块
                world[world_y][world_x] = AIR
                return True
        return False
    
    def place_block(self, world, mouse_pos, camera_x, camera_y):
        # 计算鼠标点击的世界坐标，确保转换为整数
        world_x = int((mouse_pos[0] + camera_x) // TILE_SIZE)
        world_y = int((mouse_pos[1] + camera_y) // TILE_SIZE)
        
        # 检查是否在世界范围内
        if 0 <= world_x < WORLD_WIDTH and 0 <= world_y < WORLD_HEIGHT:
            # 检查是否有物品可以放置
            if self.inventory.get(self.selected_item, 0) > 0:
                # 检查是否可以放置（不能放在玩家身上）
                player_rect = pygame.Rect(self.x, self.y, self.width, self.height)
                block_rect = pygame.Rect(world_x * TILE_SIZE, world_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
                
                if not player_rect.colliderect(block_rect) and world[world_y][world_x] == AIR:
                    # 放置方块
                    world[world_y][world_x] = self.selected_item
                    # 减少物品
                    self.inventory[self.selected_item] -= 1
                    return True
        return False

def generate_world():
    # 创建空世界
    world = [[AIR for _ in range(WORLD_WIDTH)] for _ in range(WORLD_HEIGHT)]
    
    # 生成基本地形
    for x in range(WORLD_WIDTH):
        # 基本地面高度
        base_height = WORLD_HEIGHT // 2 + random.randint(-5, 5)
        
        # 填充地下方块
        for y in range(base_height, WORLD_HEIGHT):
            # 随机生成不同的方块类型
            if y < base_height + 3:
                if y == base_height:
                    world[y][x] = GRASS_BLOCK
                else:
                    world[y][x] = DIRT_BLOCK
            else:
                # 更深的地方是石头
                if random.random() < 0.8:
                    world[y][x] = STONE_BLOCK
                else:
                    world[y][x] = DIRT_BLOCK
    
    # 添加一些随机的洞穴
    for _ in range(5):
        cave_x = random.randint(50, WORLD_WIDTH - 50)
        cave_y = random.randint(WORLD_HEIGHT // 3, WORLD_HEIGHT // 2 + 10)
        cave_size = random.randint(5, 15)
        
        for x in range(cave_x - cave_size, cave_x + cave_size):
            for y in range(cave_y - cave_size, cave_y + cave_size):
                if 0 <= x < WORLD_WIDTH and 0 <= y < WORLD_HEIGHT:
                    # 圆形洞穴
                    if (x - cave_x)**2 + (y - cave_y)**2 < cave_size**2:
                        world[y][x] = AIR
    
    return world

def draw_world(surface, world, camera_x, camera_y):
    # 计算可见区域的格子范围，确保转换为整数
    start_x = int(camera_x // TILE_SIZE)
    end_x = int((camera_x + SCREEN_WIDTH) // TILE_SIZE + 1)
    start_y = int(camera_y // TILE_SIZE)
    end_y = int((camera_y + SCREEN_HEIGHT) // TILE_SIZE + 1)
    
    # 确保在世界范围内
    start_x = max(0, start_x)
    end_x = min(WORLD_WIDTH, end_x)
    start_y = max(0, start_y)
    end_y = min(WORLD_HEIGHT, end_y)
    
    # 绘制方块
    for y in range(start_y, end_y):
        for x in range(start_x, end_x):
            block_type = world[y][x]
            if block_type != AIR:
                # 计算屏幕坐标
                screen_x = x * TILE_SIZE - camera_x
                screen_y = y * TILE_SIZE - camera_y
                
                # 根据方块类型选择颜色
                if block_type == DIRT_BLOCK:
                    color = DIRT
                elif block_type == GRASS_BLOCK:
                    color = GRASS
                elif block_type == STONE_BLOCK:
                    color = STONE
                
                # 绘制方块
                pygame.draw.rect(surface, color, (screen_x, screen_y, TILE_SIZE, TILE_SIZE))
                # 绘制边框
                pygame.draw.rect(surface, BLACK, (screen_x, screen_y, TILE_SIZE, TILE_SIZE), 1)

def draw_hotbar(surface, player):
    # 绘制物品栏背景
    hotbar_rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT - 50, 300, 40)
    pygame.draw.rect(surface, GRAY, hotbar_rect)
    pygame.draw.rect(surface, BLACK, hotbar_rect, 2)
    
    # 物品类型和对应的颜色
    item_types = [
        (DIRT_BLOCK, DIRT, "泥土 (1)"),
        (GRASS_BLOCK, GRASS, "草方块 (2)"),
        (STONE_BLOCK, STONE, "石头 (3)")
    ]
    
    # 绘制每个物品槽
    for i, (item_id, color, name) in enumerate(item_types):
        slot_x = SCREEN_WIDTH // 2 - 130 + i * 80
        slot_y = SCREEN_HEIGHT - 45
        
        # 物品槽背景
        slot_rect = pygame.Rect(slot_x, slot_y, 30, 30)
        
        # 如果是选中的物品，高亮显示
        if player.selected_item == item_id:
            pygame.draw.rect(surface, WHITE, slot_rect, 2)
        else:
            pygame.draw.rect(surface, BLACK, slot_rect, 1)
        
        # 绘制物品
        if player.inventory.get(item_id, 0) > 0:
            pygame.draw.rect(surface, color, (slot_x + 2, slot_y + 2, 26, 26))
            
            # 绘制数量
            font = pygame.font.SysFont("SimHei", 12)
            text = font.render(str(player.inventory[item_id]), True, WHITE)
            surface.blit(text, (slot_x + 20, slot_y + 15))
        
        # 绘制物品名称
        font = pygame.font.SysFont("SimHei", 12)
        text = font.render(name, True, WHITE)
        surface.blit(text, (slot_x - 10, slot_y - 15))

def update_camera(player, camera_x, camera_y):
    # 让相机跟随玩家
    target_x = player.x + player.width // 2 - SCREEN_WIDTH // 2
    target_y = player.y + player.height // 2 - SCREEN_HEIGHT // 2
    
    # 平滑相机移动
    camera_x += (target_x - camera_x) * 0.1
    camera_y += (target_y - camera_y) * 0.1
    
    # 限制相机不超出世界边界
    camera_x = max(0, min(camera_x, WORLD_WIDTH * TILE_SIZE - SCREEN_WIDTH))
    camera_y = max(0, min(camera_y, WORLD_HEIGHT * TILE_SIZE - SCREEN_HEIGHT))
    
    return camera_x, camera_y

def draw_instructions(surface):
    font = pygame.font.SysFont("SimHei", 14)
    instructions = [
        "控制说明:",
        "左右箭头键: 移动",
        "空格键: 跳跃",
        "鼠标左键: 挖掘方块",
        "鼠标右键: 放置方块",
        "1/2/3键: 切换物品"
    ]
    
    for i, text in enumerate(instructions):
        text_surface = font.render(text, True, WHITE)
        surface.blit(text_surface, (10, 10 + i * 20))

def main():
    # 生成世界
    world = generate_world()
    
    # 创建玩家
    player = Player(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
    
    # 相机位置
    camera_x = 0
    camera_y = 0
    
    # 游戏主循环
    running = True
    while running:
        # 处理事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                
            # 处理鼠标点击
            if event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                if event.button == 1:  # 左键
                    player.mine_block(world, mouse_pos, camera_x, camera_y)
                elif event.button == 3:  # 右键
                    player.place_block(world, mouse_pos, camera_x, camera_y)
        
        # 清屏
        screen.fill(BLACK)
        
        # 移动玩家
        player.move(world)
        
        # 更新相机
        camera_x, camera_y = update_camera(player, camera_x, camera_y)
        
        # 绘制世界
        draw_world(screen, world, camera_x, camera_y)
        
        # 绘制玩家
        player.draw(screen, camera_x, camera_y)
        
        # 绘制物品栏
        draw_hotbar(screen, player)
        
        # 绘制操作说明
        draw_instructions(screen)
        
        # 更新屏幕
        pygame.display.flip()
        
        # 控制帧率
        clock.tick(60)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()